/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.commons.runtime.msu;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import io.iec.edp.caf.commons.runtime.msu.entities.MsuCommonInfo;
import io.iec.edp.caf.commons.runtime.msu.entities.ServiceUnitYaml;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * msu配置读取工具类
 * 包含了一些序列化等操作
 * todo 工具类解耦后考虑使用序列化工具
 */
public class MsuConfigReader {

    //序列化工具
    private static ObjectMapper objectMapper = new ObjectMapper();

    private static Log log = LogFactory.getLog(MsuConfigReader.class);

    static public MsuCommonInfo analysisMsuInfo(String jsonString){
        MsuCommonInfo result = new MsuCommonInfo();
        try{
            String jsonStrTmp = jsonString.substring(jsonString.indexOf(":") + 1, jsonString.lastIndexOf("}"));
            if(jsonStrTmp.length()==0){
                throw new RuntimeException("A ServiceUnit.json has no content.");
            }
            result = objectMapper.readValue(jsonStrTmp, MsuCommonInfo.class);
        }catch(Throwable e){
            log.error("Get Su from ServiceUnit.json error, content is: "
                    +jsonString+" failed reason: "+ e.getMessage());
        }
        return result;
    }

    static public ServiceUnitYaml analysisMsuYamlInfo(Map<String,Object> yamlContent){
        ServiceUnitYaml result = new ServiceUnitYaml();
        try {
            result = objectMapper.readValue(objectMapper.writeValueAsString(yamlContent),ServiceUnitYaml.class);
        } catch (Throwable e) {
            log.error("Get Su from service-unit.yaml error, content is: "
                    +yamlContent+" failed reason: "+ e.getMessage());
        }
        return result;
    }

    /**
     * @param content caf_serviceunit.json文件内容
     * @param allSu 环境中所有su(包括未启用的)
     */
    static public List<String> getEnableSuListFromJson(String content, List<String> allSu){
        List<String> enableSuList = new ArrayList<>();
        //没有su信息则为空
        if(allSu == null) return enableSuList;

        //json配置是否为黑白名单
        boolean isBlackList = true;
        if (content==null||"".equals(content)) {
            log.error("Caf_ServiceUnit.json has no content");
            return new ArrayList<>();
        }
        try{
            //caf_serviceunit.json中的su信息列表
            List<Map<String,Object>> suList = new ArrayList<>();
            //序列化文件
            Map<String,Object> deployConfig = objectMapper.readValue(content,Map.class);
            if(deployConfig==null){
                throw new RuntimeException("Can't read Caf_ServiceUnit.json");
            }
            //获取配置类对象
            Map<String,Object> deploymentConfiguration = (Map)deployConfig.get(MsuConfigVariable.CAF_JSON);

            if(deploymentConfiguration.containsKey(MsuConfigVariable.CAF_JSON_STRATEGY)){
                isBlackList = !deploymentConfiguration.get(MsuConfigVariable.CAF_JSON_STRATEGY).toString().equalsIgnoreCase("WhiteList");
            }
            //获取su信息列表
            if(deploymentConfiguration.containsKey(MsuConfigVariable.CAF_JSON_SU))
                suList = (List)deploymentConfiguration.get(MsuConfigVariable.CAF_JSON_SU);

            //获取启用列表和禁用列表
            List<String> disableSu = new ArrayList<>();
            List<String> ableSu = new ArrayList<>();

            //全部转成小写
            suList.forEach(su->{
                if(su.containsKey(MsuConfigVariable.CAF_JSON_SU_NAME)&&su.containsKey(MsuConfigVariable.CAF_JSON_SU_ENABLE))
                    if((boolean)su.get(MsuConfigVariable.CAF_JSON_SU_ENABLE)){
                        ableSu.add(su.get(MsuConfigVariable.CAF_JSON_SU_NAME).toString());
                    }else{
                        disableSu.add(su.get(MsuConfigVariable.CAF_JSON_SU_NAME).toString());
                    }
            });
            if(isBlackList){
                //黑名单则将su信息列表中的被禁用的su，从全部列表中去除
                allSu.forEach(su->{
                    boolean addAble = true;
                    for(String yamlSu:disableSu){
                        if(yamlSu.equalsIgnoreCase(su)){
                            addAble = false;
                            break;
                        }
                    }
                    if(addAble&&!enableSuList.contains(su)&&su!=null) enableSuList.add(su);
                });
            }else{
                //白名单则只将全部su中包含白名单的加入
                allSu.forEach(su->{
                    boolean addAble = false;
                    for(String yamlSu:ableSu){
                        if(yamlSu.equalsIgnoreCase(su)){
                            addAble = true;
                            break;
                        }
                    }
                    if(addAble&&!enableSuList.contains(su)&&su!=null) enableSuList.add(su);
                });
            }


        }catch (Exception e){
            log.error("Get info from Caf_ServiceUnit.json error,error reason: "+ e.getMessage()
                    +" Caf_ServiceUnit.json info :\n" + content);
        }finally {
            return enableSuList;
        }

    }

    static public List<String> getEnableSuListFromYaml(Map<String,Object> yamlContent,List<String> allSu){
        List<String> enableSus = new ArrayList<>();
        //没有su信息则为空
        if(allSu == null) return enableSus;

        //yaml配置是否为黑白名单
        boolean isBlackList = true;

        //如果yaml中有配置
        try{
            if(yamlContent.containsKey(MsuConfigVariable.CAF_YAML)){
                Map config = (Map)yamlContent.get(MsuConfigVariable.CAF_YAML);
                String yamlSuString = "";
                if(config!=null){
                    if(config.containsKey(MsuConfigVariable.CAF_YAML_STRATEGY))
                        isBlackList = (!"whitelist".equalsIgnoreCase((String)config.get(MsuConfigVariable.CAF_YAML_STRATEGY)));
                    if(config.containsKey(MsuConfigVariable.CAF_YAML_SU))
                        yamlSuString = (String) config.get(MsuConfigVariable.CAF_YAML_SU);
                }
                if(yamlSuString == null) yamlSuString = "";
                //按,分割
                List<String> yamlSuList = Arrays.asList(yamlSuString.split(","));


                if(isBlackList){
                    //黑名单被禁用的su，从全部列表中去除
                    allSu.forEach(su->{
                        boolean addAble = true;
                        for(String yamlSu:yamlSuList){
                            yamlSu = yamlSu.trim();
                            if(yamlSu.equalsIgnoreCase(su)){
                                addAble = false;
                                break;
                            }
                        }
                        if(addAble&&!enableSus.contains(su)&&su!=null) enableSus.add(su);
                    });
                }else{
                    //白名单则验证是否在全部列表中
                    allSu.forEach(su->{
                        boolean addAble = false;
                        for(String yamlSu:yamlSuList){
                            yamlSu = yamlSu.trim();
                            if(yamlSu.equalsIgnoreCase(su)){
                                addAble = true;
                                break;
                            }
                        }
                        if(addAble&&!enableSus.contains(su)&&su!=null) enableSus.add(su);
                    });
                }

            }
            else {
                return null;
            }
        }catch (Throwable e){
            log.error("Get msu info error from application.yaml, content is: "+yamlContent,e);
        }



        return enableSus;
    }

    static {
        //对象的所有字段全部列入
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //取消默认转换timestamps形式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
        //忽略空Bean转json的错误
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
        //所有的日期格式都统一为以下的样式，即yyyy-MM-dd HH:mm:ss
//        objectMapper.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT));
        //忽略 在json字符串中存在，但是在java对象中不存在对应属性的情况。防止错误
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        //设置可用单引号
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        //设置字段可以不用双引号包括
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

        //https://blog.csdn.net/qfzhangwei/article/details/85009163
        objectMapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN,true);
        objectMapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN,true);
        //允许缺少数据
        objectMapper.configure(JsonParser.Feature.ALLOW_MISSING_VALUES,true);
        //大小写脱敏 默认为false  需要改为true
        objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES,true);
        //OffsetTimeDate保留时区
        objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
    }
}
